﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using BbsbWebService.Service;
using System.Net.Sockets;
using System.Net;
using BbsbWebService.Enums;
using BbsbWebService.Classes;
using Microsoft.Win32;
using System.Reflection;
using BbsbWebService.Repositories;
using System.Threading;
using BbsbWebService.Tasks;
using BbsbWsGui;

namespace BbsbWebService
{
    /// <summary>
    /// Interaction logic for Window1.xamlni
    /// </summary>
    public partial class Window1 : Window
    {
        #region Private Members

        bool _isClientMode = false;
        bool _isRunning = false;
        const string _appName = "BBSBWS";
        RegistryKey _rkApp = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);

        #endregion

        public Window1()
        {
            try
            {
                InitializeComponent();
                SetupTaskbarStuff();

                // Initialise the GUI settings (which in turn initialises all settings)
                GuiSettings.Instance.Initialise();

                // See if there are any servers already on the network
                ApplicationState.SniffForServer();

                // Clear and Initialise all of the repositories
                RepositoryInstances.Refresh();

                // Refresh the ItemsSource for all the Grids
                RefreshItems();

                // Define which panel is shown at the top
                SetTopPanel();

                // If we're a server and prefer it, start service straight away
                if (!ApplicationState.IsClient && GuiSettings.Instance.StartServiceOnLoad)
                {
                    StartService();
                }
            }
            catch (Exception ex)
            {
                Logging.Logger.Instance.LogException(ex, "Error starting application");
            }
        }

        #region Setup Methods

        private void SetupTaskbarStuff()
        {
            System.Windows.Forms.NotifyIcon ni = new System.Windows.Forms.NotifyIcon();
            System.Drawing.Icon theIcon = new System.Drawing.Icon(System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("BbsbWsGui.Icon.ico"));
            ni.Icon = theIcon;
            ni.Visible = true;
            ni.DoubleClick +=
            delegate(object sender, EventArgs args)
            {
                this.Show();
                this.WindowState = WindowState.Normal;
            };
        }

        private void SetWindowsStartupCheckbox()
        {
            if (_rkApp.GetValue(_appName) == null)
            {
                // The value doesn't exist, the application is not set to run at startup
                windowsStartupChk.IsChecked = false;
            }
            else
            {
                // The value exists, the application is set to run at startup
                windowsStartupChk.IsChecked = true;
            }
        }

        protected override void OnStateChanged(EventArgs e)
        {
            if (WindowState == WindowState.Minimized)
                this.Hide();
            base.OnStateChanged(e);
        }

        private void SetTopPanel()
        {
            if (ApplicationState.IsConnectedToClient)
            {
                ServerPanel.Visibility = Visibility.Hidden;
                ClientPanel.Visibility = Visibility.Visible;
                clientDisconnectedPanel.Visibility = Visibility.Hidden;
                serverModeRdo.Visibility = System.Windows.Visibility.Hidden;
                clientModeRdo.Visibility = System.Windows.Visibility.Hidden;

                string serverAddress = ApplicationState.ServerMachine.ComputerName;
                ClientLbl.Text = serverAddress;

                SetAllFieldEnabledProperties(true);
            }
            else if (_isClientMode)
            {
                ServerPanel.Visibility = Visibility.Hidden;
                ClientPanel.Visibility = Visibility.Hidden;
                clientDisconnectedPanel.Visibility = Visibility.Visible;
                serverModeRdo.Visibility = System.Windows.Visibility.Visible;
                clientModeRdo.Visibility = System.Windows.Visibility.Visible;

                if (ApplicationState.IsClient)
                {
                    clientNameTxt.Text = ApplicationState.ServerMachine.ComputerName;
                    clientPortTxt.Text = ApplicationState.ServerMachine.Port.ToString();
                }

                SetAllFieldEnabledProperties(false);
            }
            else
            {
                ServerPanel.Visibility = Visibility.Visible;
                ClientPanel.Visibility = Visibility.Hidden;
                clientDisconnectedPanel.Visibility = Visibility.Hidden;
                serverModeRdo.Visibility = System.Windows.Visibility.Visible;
                clientModeRdo.Visibility = System.Windows.Visibility.Visible;

                portTxt.Text = GuiSettings.Instance.Port.ToString();
                startServiceOnStart.IsChecked = GuiSettings.Instance.StartServiceOnLoad;
                SetWindowsStartupCheckbox();
                logChk.IsChecked = GuiSettings.Instance.Log;

                SetAllFieldEnabledProperties(true);
            }
        }

        private void SetAllFieldEnabledProperties(bool enabled)
        {
            // TODO: Set Enabled properties for all elements on the screen
            tabControl1.IsEnabled = enabled;

            itemsTab.Enabled = enabled;

            groupsTab.Enabled = enabled;

            tasksTab.Enabled = enabled;
        }

        #endregion

        #region Service Methods

        private void startBtn_Click(object sender, RoutedEventArgs e)
        {
            StartService();
        }

        private void StartService()
        {
            int port;
            if (int.TryParse(portTxt.Text, out port))
            {
                if (GuiSettings.Instance.Port != port)
                {
                    GuiSettings.Instance.Port = port;
                    GuiSettings.Instance.Save();
                }
                ApplicationState.StartService();
                ToggleButtons();
            }
            else
            {
                MessageBox.Show("Invalid port value");
            }
        }

        private void stopBtn_Click(object sender, RoutedEventArgs e)
        {
            ToggleButtons();
            ApplicationState.StopService();
        }

        private void ToggleButtons()
        {
            _isRunning = !_isRunning;
            startBtn.IsEnabled = !_isRunning;
            stopBtn.IsEnabled = _isRunning;
            portTxt.IsEnabled = !_isRunning;
            serverModeRdo.IsEnabled = !_isRunning;
            clientModeRdo.IsEnabled = !_isRunning;
            if (!_isRunning)
            {
                indicatorRct.Fill = new SolidColorBrush(Colors.Red);
            }
            else
            {
                indicatorRct.Fill = new SolidColorBrush(Colors.Green);
            }
        }

        private void logChk_Unchecked(object sender, RoutedEventArgs e)
        {
            SetLog();
        }

        private void logChk_Checked(object sender, RoutedEventArgs e)
        {
            SetLog();
        }

        private void SetLog()
        {
            if (GuiSettings.Instance.Log != logChk.IsChecked == true)
            {
                GuiSettings.Instance.Log = logChk.IsChecked == true;
                GuiSettings.Instance.Save();
            }

            if (GuiSettings.Instance.Log)
            {
                Logging.Logger.Instance.RegisterLogger(new Logging.FileLogger());
            }
            else
            {
                Logging.Logger.Instance.UnregisterLogger(new Logging.FileLogger());
            }
        }

        private void startServiceOnStart_Checked(object sender, RoutedEventArgs e)
        {
            SetServiceStart();
        }

        private void startServiceOnStart_Unchecked(object sender, RoutedEventArgs e)
        {
            SetServiceStart();
        }

        private void windowsStartupChk_Checked(object sender, RoutedEventArgs e)
        {
            // Add the value in the registry so that the application runs at startup
            _rkApp.SetValue(_appName, Assembly.GetExecutingAssembly().Location);
        }

        private void windowsStartupChk_Unchecked(object sender, RoutedEventArgs e)
        {
            // Remove the value from the registry so that the application doesn't start
            _rkApp.DeleteValue(_appName, false);
        }

        private void SetServiceStart()
        {
            if (GuiSettings.Instance.StartServiceOnLoad != startServiceOnStart.IsChecked)
            {
                GuiSettings.Instance.StartServiceOnLoad = startServiceOnStart.IsChecked.Value;
                GuiSettings.Instance.Save();
            }
        }

        #endregion

        private void RefreshItems()
        {
            itemsTab.ItemsSource = RepositoryInstances.ItemRepository.Items;
            //allItemsLst.Items.Refresh();
            groupsTab.ItemsSource = RepositoryInstances.GroupRepository.Items;
            //groupsLst.Items.Refresh();
            tasksTab.ItemsSource = RepositoryInstances.TaskRepository.Items;
            //tasksLst.Items.Refresh();
            //UpdateGroupItems();
        }

        private void clientDisconnect_Click(object sender, RoutedEventArgs e)
        {
            // TODO: Disconnect from the server
            ApplicationState.IsConnectedToClient = false;
            _isClientMode = true;
            SetTopPanel();
        }

        private void clientConnect_Click(object sender, RoutedEventArgs e)
        {
            string computerName = clientNameTxt.Text;
            int port;
            if (!computerName.IsNullOrEmpty() &&
                int.TryParse(clientPortTxt.Text, out port))
            {
                ServerItem server = new ServerItem
                {
                    ComputerName = computerName,
                    Port = port
                };

                ApplicationState.ServerMachine = server;
                try
                {
                    RepositoryInstances.Refresh();

                    // is successful connection
                    ApplicationState.IsConnectedToClient = true;
                    SetTopPanel();
                }
                catch (Exception ex)
                {
                    ApplicationState.ServerMachine = null;
                    Logging.Logger.Instance.LogException(ex, "Error connecting to server: {0}", server.ToBbsbServiceAddress());
                }
            }

            if (!ApplicationState.IsConnectedToClient)
            {
                // Ensure there's been no initialisation of the Repositories
                RepositoryInstances.Reset();
                MessageBox.Show("Error connecting to the requested server.");
            }
        }

        private void serverModeRdo_Checked(object sender, RoutedEventArgs e)
        {
            if (!IsInitialized) return;

            _isClientMode = false;
            SetTopPanel();
        }

        private void clientModeRdo_Checked(object sender, RoutedEventArgs e)
        {
            if (!IsInitialized) return;

            _isClientMode = true;
            SetTopPanel();
        }
    }
}
